#pragma once

namespace qyc
{
	#ifdef _WIN64
		typedef unsigned __int64 size_t;
	#else
		typedef unsigned int     size_t;
	#endif

	template<class T>
	struct remove_reference
	{
		typedef T type;
	};
	template <class T>
	struct remove_reference<T&>
	{
		typedef T type;
	};
	template <class T>
	struct remove_reference<T&&>
	{
		typedef T type;
	};
	template<class T>
	using remove_ref = typename qyc::remove_reference<T>::type;

	template<class T>
	remove_ref<T>&& move(T&& right)
	{
		return static_cast<remove_ref<T>&&>(right);
	}

	template<class T>
	T&& forward(remove_ref<T>& right)
	{
		return static_cast<T&&>(right);
	}
	template<class T>
	T&& forward(remove_ref<T>&& right)
	{
		return static_cast<T&&>(right);
	}

	template<class T>
	void swap(T& left, T& right)
	{
		T tmp = qyc::move(left);
		left = qyc::move(right);
		right = qyc::move(tmp);
	}

	template<class T1, class T2>
	struct pair
	{
	private:
		typedef T1 first_type;
		typedef T2 second_type;
		typedef pair<first_type, second_type> self;
	public:
		pair()
			: first()
			, second()
		{}
		pair(const first_type& _First, const second_type& _Second)
			: first(_First)
			, second(_Second)
		{}
		pair(first_type&& _First, const second_type& _Second)
			: first(qyc::forward<first_type>(_First))
			, second(_Second)
		{}
		pair(const first_type& _First, second_type&& _Second)
			: first(_First)
			, second(qyc::forward<second_type>(_Second))
		{}
		pair(first_type&& _First, second_type&& _Second)
			: first(qyc::forward<first_type>(_First))
			, second(qyc::forward<second_type>(_Second))
		{}

		void swap(self& des)
		{
			qyc::swap(first, des.first);
			qyc::swap(second, des.second);
		}

		first_type first;
		second_type second;
	};

	template<class T1, class T2>
	pair<T1, T2> make_pair(const T1& first, const T2& second)
	{
		return pair<T1, T2>(first, second);
	}

	template <class Ty1, class Ty2, class Uty1, class Uty2>
	bool operator==(const pair<Ty1, Ty2>& _Left, const pair<Uty1, Uty2>& _Right)
	{
		return _Left.first == _Right.first && _Left.second == _Right.second;
	}
	template <class Ty1, class Ty2, class Uty1, class Uty2>
	bool operator<(const pair<Ty1, Ty2>& _Left, const pair<Uty1, Uty2>& _Right)
	{
		return _Left.first < _Right.first || (!(_Right.first < _Left.first) && _Left.second < _Right.second);
	}
	template <class Ty1, class Ty2, class Uty1, class Uty2>
	bool operator>(const pair<Ty1, Ty2>& _Left, const pair<Uty1, Uty2>& _Right)
	{
		return _Right < _Left;
	}
	template <class Ty1, class Ty2, class Uty1, class Uty2>
	bool operator<=(const pair<Ty1, Ty2>& _Left, const pair<Uty1, Uty2>& _Right)
	{
		return !(_Right < _Left);
	}
	template <class Ty1, class Ty2, class Uty1, class Uty2>
	bool operator>=(const pair<Ty1, Ty2>& _Left, const pair<Uty1, Uty2>& _Right)
	{
		return !(_Left < _Right);
	}
}